#coding:utf-8
'''
* coder  : dzlua
* email  : 505544956@qq.com
* module : ApiMgr-server
* path   : app/apis
* file   : auth.py
* time   : 2017-11-07 17:22:04
'''
#--------------------#
from flask import g
from flask_restful import Resource
from flask_restful import reqparse
from flask_restful import inputs
#----------#
from app.mgr import auth
from app.mgr import api
#----------#
from app.models.user import User
from app.models.auth import Token
#----------#
from app.utils.response import *
from app.utils.helper import send_email
#--------------------#

#--------------------#
@api.resource('/refresh_token')
class RefreshToken(Resource):
    decorators = [auth.required_login]
    #
    def post(self):
        data = { 'user_id': g.user.id }
        refresh_token = auth.generate_refresh_token(data)
        return makeResponse( R200_OK, {
            'token': refresh_token,
            'expires_in': auth.rfexpires_in,
            'username': g.user.username,
        } )
#--------------------#

#--------------------#
@api.resource('/access_token')
class AccessToken(Resource):
    decorators = [auth.required_refresh_token]
    #
    def post(self):
        data = { 'user_id': g.user.id }
        access_token = auth.generate_access_token(data)
        return makeResponse( R200_OK, {
            'access_token': access_token,
            'expires_in': auth.aexpires_in,
            'username': g.user.username,
        } )
#--------------------#

#--------------------#
@api.resource('/token', '/login')
class Login(Resource):
    decorators = [auth.required_multi_refresh]
    #
    def post(self):
        data = { 'user_id': g.user.id }
        refresh_token = auth.generate_refresh_token(data)
        access_token = auth.generate_access_token(data)
        return makeResponse( R200_OK, {
            'refresh_token': refresh_token,
            'refresh_expires_in': auth.rfexpires_in,
            'access_token': access_token,
            'access_expires_in': auth.aexpires_in,
            'username': g.user.username,
        } )
#--------------------#

#--------------------#
@api.resource('/logout')
class Logout(Resource):
    decorators = [auth.required_multi_access]
    #
    def post(self):
        token = Token.get(user_id=g.user.id)
        if token:
            token.refresh_token = None
            token.access_token = None
            token.update()
        return makeResponse(R200_OK, 'logout')
#--------------------#

#--------------------#
@api.resource('/register_email')
class RegisterEmail(Resource):
    parser = reqparse.RequestParser()
    parser.add_argument('username', required=True,
        type=inputs.regex(r'^[A-Za-z0-9_\-\u4e00-\u9fa5]{3,16}$'),
        help='The username format is correct?')
    parser.add_argument('password', required=True,
        type=inputs.regex(r'^(.){6,16}$'),
        help='The password format is correct?')
    parser.add_argument('email', required=True,
        type=inputs.regex(r'^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$'),
        help='The email format is correct?')
    parser.add_argument('phone', required=False,
        type=inputs.regex(r'1\d{10}'),
        help='The phone format is correct?')
    #
    def post(self):
        args = self.parser.parse_args()
        username = args.get('username')
        email = args.get('email')
        phone = args.get('phone')
        #
        # check username
        user = User.get(username=username)
        if user:
            return makeResponse(R409_Conflict,
                msg='username %s already exists.' % username)
        # check email
        user = User.get(email=email)
        if user:
            return makeResponse(R409_Conflict,
                msg='email %s already exists.' % email)
        if phone:
            # check phone
            user = User.get(phone=phone)
            if user:
                return makeResponse(R409_Conflict,
                    msg='phone %s already exists.' % phone)
        #
        password = args.get('password')
        User.add(
            username=username,
            password=password,
            email=email,
            phone=phone )
        #
        return makeResponse(R200_OK)
#--------------------#

#--------------------#
@api.resource('/send_verify_email')
class SendVerifyEmail(Resource):
    decorators = [auth.required_multi_refresh]
    #
    parser = reqparse.RequestParser()
    parser.add_argument('url', required=True,
        type=inputs.url,
        help='The url format is correct?.')
    #
    def post(self):
        args = self.parser.parse_args()
        url = args.get('url')

        token = auth.generate_user_token({
            'user_id': g.user.id,
            'type': 'email'
        })

        uri = url + '?token=' + token

        send_email(
            'verify your email',
            recipients=[g.user.email],
            body=uri)

        return makeResponse(R200_OK)
#--------------------#

#--------------------#
@api.resource('/verify_email')
class VerifyEmail(Resource):
    decorators = [auth.required_user_token]
    #
    def post(self):
        if g.data['type'] != 'email':
            return makeResponse(R401_UNAUTHORIZED)
        #
        token = Token.get(user_id=g.user.id)
        if not token:
            return makeResponse(R401_UNAUTHORIZED)
        #
        if g.user.email_verifyed:
            return makeResponse(R409_Conflict, msg='Has been verified.')
        #
        g.user.email_verifyed = True
        g.user.update()
        token.email_token = None
        token.update()
        #
        return makeResponse(R200_OK)
#--------------------#
